using System;
using Gtk;

using RapidLoad;
using System.Timers;
using System.Reflection;

public partial class MainWindow : Gtk.Window
{	
	// defines in what interval in msecs this
	// UI should update its data from the sources
	public const double UpdateInterval = 500;
	
	// the users rapidshare account
	private RapidAccount UserAccount;
	
	// timer that pulls the update
	private Timer UpdateTimer;
	
	/// <summary>
	/// Constructs the window and
	/// therefor shows the App UI 
	/// </summary>
	public MainWindow () : base(Gtk.WindowType.Toplevel)
	{
		Build ();
		// set the window title
		this.Title = Assembly.GetExecutingAssembly().GetName().Name
				   + " v" + Assembly.GetExecutingAssembly().GetName().Version;
		
		// request user to login
		this.UserAccount = this.RequestLogin();
		
		// update the account info table
		this.UpdateAccountInfoTable();
		
		this.UpdateTimer = new Timer(MainWindow.UpdateInterval);
		// create a delegate that catches the elapsed event
		this.UpdateTimer.Elapsed += delegate(object sender, ElapsedEventArgs e) {
										// forces the UI to update on elapsed-event
										this.UpdateUI();
									};
		// initially start the timer
		// and stop on disposed event
		this.UpdateTimer.Start();
	}
	
	/// <summary>
	/// Requests all widgets to update
	/// their data from their datasources 
	/// </summary>
	public void UpdateUI(){
		this.MainInventoryView.Update();
		this.ShowAll();
	}
	
	/// <summary>
	///	method displays the login dialog
	/// and requests the user to login 
	/// </summary>
	/// <returns>
	/// The <see cref="RapidAccount"/> that the
	/// user entered in the dialog.
	/// </returns>
	private RapidAccount RequestLogin(){
		// users account that this method returns
		RapidAccount UserAccount = new RapidAccount();
		
		// create the dialog and run it
		AccountLogin LoginWindow = new AccountLogin();
		ResponseType LoginResponse = (ResponseType)LoginWindow.Run();
		
		if(LoginResponse == ResponseType.Ok){			
			// finally login
			bool isLoggedIn = UserAccount.Login(LoginWindow.Username, 
			                  					LoginWindow.Password);
			if(isLoggedIn){
				// set inventory to inventory's view
				this.MainInventoryView.setInventory(UserAccount.Inventory);
			}else{
				// show an error message
				MsgBox.Show("Invalid login details.", 
					"Unable to log in", MessageType.Error);
				// exit the application
				Environment.Exit(0);
			}
		}else{
			// closes the app when
			// login is not performed
			Environment.Exit(0);
		}
		
		// destroy the window now
		LoginWindow.Destroy();
		
		// return the newly created account
		return UserAccount;
	}
	
	/// <summary>
	/// Updates the displayed table with
	/// the account information 
	/// </summary>
	private void UpdateAccountInfoTable(){		
		// displays the id, username and account type
		this.AccountIdValueLabel.Text = this.UserAccount.Id.ToString();
		this.AccountUsernameValueLabel.Text = this.UserAccount.Username;

		// display the traffic limits when its a premium account
		this.AccountExpiresValueLabel.Text 
					= this.UserAccount.BilledUntil.ToShortDateString();
		this.AccountTrafficValueLabel.Text 
					= Utils.MakeByteString(this.UserAccount.TrafficAmount);

		// both account types 'col' and 'prem' have
		// the chance to collect free and premium points
		this.AccountRapidsValueLabel.Text 
				= String.Format("{0:#,#}", this.UserAccount.Rapids);
		this.AccountServerTimeValueLabel.Text 
				= this.UserAccount.ServerTime.ToString();
		
		// update the statusbar with the account number
		this.MainStatus.Push(0, "Account " 
		                     + this.UserAccount.Id.ToString() 
		                     + ": No files active");
	}

	/// <summary>
	/// Exits the application when the window is closed
	/// </summary>
	protected void OnDeleteEvent (object sender, DeleteEventArgs a)
	{
		this.UpdateTimer.Stop();
		Application.Quit ();
		a.RetVal = true;
	}
	
	/// <summary>
	/// Opens a new CreatePackage window when
	/// the user clicks the new action. That
	/// window fires and event which is handled
	/// and then the created package is added.
	/// 
	/// multiple CreatePackage windows can be
	/// shown and they are not modal, so that
	/// the user can control the load list while
	/// creating new packages for it
	/// </summary>
	protected virtual void OnNewActionActivated (object sender, System.EventArgs e)
	{
		// create the window
		CreatePackage CreatePackageWindow = new CreatePackage
					(new RapidPackage(this.UserAccount.Cookie));
		// bind the created event to the local handler
		CreatePackageWindow.PackageCreated += HandleCreatePackageWindowPackageCreated;
		// and then show the window
		CreatePackageWindow.ShowAll();
	}

	/// <summary>
	/// handles the event when a package
	/// has been created and then adds that
	/// new package to the user accounts inventory
	/// 
	/// afterwards it refreshes the list
	/// </summary>
	void HandleCreatePackageWindowPackageCreated (object sender, EventArgs e)
	{
		// adds package to the accounts inventory
		PackageCreatedEventArgs createdArgs = (PackageCreatedEventArgs)e;
		this.UserAccount.Inventory.AddPackage(createdArgs.createdPackage);
	}
	
	/// <summary>
	/// Handles the change of the number
	/// of concurrent downloads and set
	/// the value to the underlying inventory
	/// </summary>
	protected virtual void OnConcurrentDownloadsSpinValueChanged (object sender, System.EventArgs e)
	{
		// sets the number of concurrent downloads
		this.UserAccount.Inventory.SetNumberOfConcurrentDownloads
					((int)this.ConcurrentDownloadsSpin.Value);
	}
	
	protected virtual void OnStopActionActivated (object sender, System.EventArgs e)
	{
		this.MainInventoryView.StopSelectedPackage();
	}
	
	protected virtual void OnDownloadActionActivated (object sender, System.EventArgs e)
	{
		this.MainInventoryView.StartSelectedPackage();
	}
	
	
	
	
	
}
